package cn.monkey.family.server.data;

import cn.monkey.family.data.Result;
import cn.monkey.family.data.Results;
import cn.monkey.family.data.uc.role.Role;
import cn.monkey.family.data.uc.role.RoleQueryRequest;
import cn.monkey.family.data.uc.role.RoleType;
import cn.monkey.family.data.uc.user.User;
import cn.monkey.family.data.uc.user.UserQueryRequest;
import cn.monkey.family.data.uc.user.role.UserRole;
import cn.monkey.family.server.domain.uc.auth.password.PasswordEncoder;
import cn.monkey.family.server.domain.uc.role.RoleRepository;
import cn.monkey.family.server.domain.uc.user.UserRepository;
import cn.monkey.family.server.domain.uc.user.role.UserRoleRepository;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Optional;

@Configuration
public class DataInitializerConfig {

    record DataInitializerRunner(UserRepository userRepository,
                                 PasswordEncoder passwordEncoder,
                                 RoleRepository roleRepository,
                                 UserRoleRepository userRoleRepository) implements ApplicationRunner {

        Result<User> tryCreateAccount() {
            User user = new User();
            user.setAccount("admin");
            user.setPassword(this.passwordEncoder.encode("admin"));
            user.setMobile("13800000000");
            user.setEmail("admin@monkey.cn");
            user.setEnabled(true);
            user.setNickName("管理员");
            Optional<User> userOptional = this.userRepository.findOneByQueryRequest(UserQueryRequest.builder()
                    .account("admin").build());
            if (userOptional.isPresent()) {
                return Results.fail("exist user");
            }
            return Results.ok(this.userRepository.save(user));
        }

        Result<Role> tryCreateAdminRole() {
            Role role = new Role();
            role.setType(RoleType.ADMIN.getKey());
            role.setName(RoleType.ADMIN.getValue());
            role.setEnabled(true);
            Optional<Role> roleOptional = this.roleRepository.findOneByQueryRequest((RoleQueryRequest.builder().type(RoleType.ADMIN.getKey()).build()));
            if (roleOptional.isPresent()) {
                return Results.ok(roleOptional.get());
            }
            return roleOptional.map(Results::ok)
                    .orElse(Results.ok(this.roleRepository.save(role)));
        }


        @Override
        public void run(ApplicationArguments args) throws Exception {
            Result<User> userResult = this.tryCreateAccount();
            Result<Role> roleResult = this.tryCreateAdminRole();
            if (Results.isOk(userResult)) {
                this.bindUserRoleRel(userResult.getData(), roleResult.getData());
            }
        }

        private void bindUserRoleRel(User user, Role role) {
            UserRole userRole = new UserRole();
            userRole.setUid(user.getId());
            userRole.setRoleId(role.getId());
            userRoleRepository.save(userRole);
        }
    }

    @Bean
    DataInitializerRunner dataInitializerRunner(UserRepository userRepository,
                                                PasswordEncoder passwordEncoder,
                                                RoleRepository roleRepository,
                                                UserRoleRepository userRoleRepository) {
        return new DataInitializerRunner(userRepository, passwordEncoder, roleRepository, userRoleRepository);
    }
}
